

from bf_parsedoc import *

table2 = {

    "$block": Pat("block", list),
    # ~ "$if": Pat("Pif", ((Pat('Lif', None), dict), listb)),
    "$if": Pat("Pif", ((Pat('Lif', None), dict-cu-"ifx"), list-cu-"ifb")),
    "$ifelse": Pat("Pifelse", ((Pat('Lelse', None), object), "$if", list-cu-"elseb")),
    "$ifelif": Pat("Pifelif", ((Pat('Lelif', None), dict-cl-"elifx"), ["$if", "$ifelif"], list-cl-"elifb")),
    "$ifelifelse": Pat("Pifelifelse", ((Pat('Lelse', None), object), "$ifelif", list-cu-"elseb")),
    "$for": Pat("Pfor", ((Pat('Lfor', None), dict-cu-"forxl"), list-cu-"forb")),

    "$_other": Pat('???', object),
    "part": Pat("part", ["$if", "$ifelse", "$ifelif", '$ifelifelse', '$for']-cu-"part")

  #  "part": Pat("part", ["$if", "$ifelse", "$ifelifelse", "$forelse"]-cu-"code")

}

link(table2)



def trans_part(tree):
    b, d = match_collect(tree, table2["part"])
    if b:
        #print("match***************")
        a = d["part"]
        return (a[0].name, a[1])
    else:
        return tree
       # raise Exception("无法转换")



def parsedoc_step2(l):       
    def do(t):  # 把pat转化成普通字符串
        if isinstance(t, tuple):
            a, b = t
            a = a.name
            if type(b) is dict:
                for k in b:
                    b[k] = do(b[k])
            elif a == "Orawtuple":
                b.l = [do(parseline(m)) for m in b.l]
            return (a, b)
        elif isinstance(t, listb): # block
            return [do(a)for a in t]
        elif isinstance(t, list):
            a, *b = t
            a = do(a)
            b = [do(c)for c in b]
            return (a, *b)
        else:
            return t
    l = do(l)
   # print("替换后", l)
   # return l
    return [trans_part(x) for x in l]

def parsedoc(l):
    r = parsedoc_step1(l)
    rr = parsedoc_step2(r)
    return rr

def test(s):
    doc = scan(s)
    show(doc)
    r = parsedoc_step1(doc.l)
    print(r)
    showd2(r)
    rr = parsedoc_step2(r)
    showr(rr)

def showr(r):
    from tool_treeprint import tree
    from dataclasses import dataclass
    @dataclass
    class Pair:
        a: object
        b: object
    def name(x):
        if isinstance(x, list):
            return '<'
        elif isinstance(x, tuple)and len(x) == 2 and not isinstance(x[1], (list, tuple, dict, RawTuple)):
            return str(x)
        elif isinstance(x, tuple)and isinstance(x[0], (str, Pat)):
            return str(x[0])
        elif isinstance(x, dict):
            return '{'
        elif isinstance(x, Pair):
            return name(x.a) + ':'+name(x.b)
        elif isinstance(x, RawTuple):
            return '('
        return str(x)
    
    def member(x):
        if isinstance(x, list):
            return x
        elif isinstance(x, tuple)and len(x) == 2 and not isinstance(x[1], (list, tuple, dict, RawTuple)):
            return []
        elif isinstance(x, tuple) and isinstance(x[0], (str, Pat)):
            return list(x[1:])
        elif isinstance(x, dict):
            return [Pair(a,b) for a, b in x.items()]
        elif isinstance(x, Pair):
            return member(x.b)
        elif isinstance(x, RawTuple):
            return member(x.l)
        return []
    tree(r, name, member)




if __name__ == "__main__":
    #("for i in range(5).reversed() if i % 3")
    code = """
a = input()
if a < 1:
    x.l[0] = 1
    l[0].x = 1
    3
elif a < 2:
    (x, y) = (y, x)
    4
else:
    20
print(5)
for i in range(3):
  for j in range(3):
    print(i * j) / 2

input()
    """
    # ~ code = """
# ~ a = input()
# ~ if a < 1:
    # ~ x.l[0] = 1
    # ~ l[0].x = 1
    # ~ 3
# ~ else:
    # ~ ok
# ~ 2
    # ~ """
    code = """
a = 1
if a < 1:
    print(1, 2+2)
    3
else:
    ok
2
    """

    test(code)



"""
[
    (<Lassign>, {'x': [(<Oword>, a)], 'y': (<Oexp2>, {'2f': (p@'call', 'call'), '2x': (<Oword>, input), '2y': (<Orawtuple>, ())})}),
    [(<Lif>, {'x': (<Oexp2>, {'2f': (p@'<', '<'), '2x': (<Oword>, a), '2y': (<Onum>, 1)})}),
        [
            (<Lassign>, {'x': [(<Oitem>, {'ix': (<Oexp2>, {'2f': (p@'.', '.'), '2x': (<Oword>, x), '2y': (<Oword>, l)}), 'iy': (p@<class 'object'>, [[0]])})], 'y': (<Onum>, 1)}),
            (<Lassign>, {'x': [(<Oattr>, {'ax': (<Oexp2>, {'2f': (p@'item', 'item'), '2x': (<Oword>, l), '2y': (<Orawlist>, [[0]])}), 'ay': (<Oword>, x)})], 'y': (<Onum>, 1)}),
            (<Onum>, 3)
        ]
    ],
    (<Onum>, 2)

]


"""




